package com.ruoyi.web.controller.wind;


import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.exception.ProcessStopException;
import com.ruoyi.common.utils.ExecUtil;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.SseEmitterUtils;
import com.ruoyi.common.utils.bean.ObjUtil;
import com.ruoyi.common.utils.biz.CommonUtil;
import com.ruoyi.common.utils.biz.PathUtil;
import com.ruoyi.common.utils.biz.ResultSaveModule;
import com.ruoyi.web.server.entity.ResultSave;
import com.ruoyi.web.server.service.ResultSaveService;
import com.ruoyi.web.vo.WindCharacterCalVo;
import com.ruoyi.web.vo.WindCharacterDrawVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;


/**
 * <p>
 *  风场反演
 * </p>
 *
 * @author liuhl
 * @since 2024-04-15
 */
@RestController
@RequestMapping("/character")
@AllArgsConstructor
@Slf4j
@Api(tags = "风场特征")
public class WindCharacterController {

    private ResultSaveService resultSaveService;



    @PostMapping("/cal")
    @ApiOperation(value = "风场特征-计算", notes = "根据页面入参计算出结果文件", httpMethod = "POST")
    public AjaxResult windCharacterCal(@RequestBody WindCharacterCalVo vo) throws ProcessStopException {

        String tmpDir = PathUtil.tmpDir() +
                PathUtil.moduleDirs().getModelRevise().get("dir");

        String outputDir = PathUtil.outputDir() +
                PathUtil.moduleDirs().getModelRevise().get("dir");

        String originDir = PathUtil.outputDir() +
                PathUtil.moduleDirs().getCollect().get("dir") +
                PathUtil.moduleDirs().getCollect().get("result");

        String type = vo.getType();
        List<String> command = null;
        if ("satellite".equals(type)){
            String codePath = PathUtil.codeDir() +
                    PathUtil.moduleDirs().getModelRevise().get("dir") +
                    PathUtil.moduleDirs().getModelRevise().get("satellite");

            String resultType = vo.getResultType();
            String level = ("horizon".equals(resultType) || "trajectory".equals(resultType))?vo.getLevel():"all";
            String area = CommonUtil.getArea(vo.getLongitudeRange(), vo.getLatitudeRange());
            command = Stream.of("python",
                    "-u",
                    codePath,
                    originDir,
                    outputDir,
                    tmpDir,
                    vo.getSateName(),
                    vo.getStartTime(),
                    vo.getEndTime(),
                    resultType,
                    area,
                    level,
                    vo.getMethod(),
                    //数据类型:当卫星名称为TIMED：datatype为S0450/S0302/S0200)；UARS：A/P；其他为空值(但是调Python时不能给空，否则python接不到，固定给无意义值)
                    StrUtil.isBlank(vo.getDataType())? "None":vo.getDataType()
            ).collect(Collectors.toList());

        }

        if ("radar".equals(type)){

            String codePath = PathUtil.codeDir() +
                    PathUtil.moduleDirs().getModelRevise().get("dir") +
                    PathUtil.moduleDirs().getModelRevise().get("radar");

            command = Stream.of("python",
                    "-u",
                    codePath,
                    originDir,
                    outputDir,
                    tmpDir,
                    vo.getDataName(),
                    vo.getStartTime(),
                    vo.getEndTime()
            ).collect(Collectors.toList());
        }
        String sseId = vo.getSseId()+SecurityUtils.getLoginUser().getUsername();
        String results = ExecUtil.execPython(command, sseId);
        SseEmitterUtils.remove(sseId);
        if (results == null || !results.contains("###")){
            return AjaxResult.error(results);
        }
        //###1980年01月特征分析计算, 大约需要1.5小时！######/dgdq/output/modelRevise/character/Nimbus7/1980/Nimbus7_linear_198001_character.nc###风场特征分析计算完成！
        String[] splitArr = results.split("###");
        List<String> resultDataList = Arrays.asList(splitArr).stream()
                .filter(path -> path.contains(".nc"))
                .map(String::trim)
                .collect(Collectors.toList());

        List<String> fileNameList = resultDataList
                .stream()
                .map(filePath -> filePath.substring(filePath.lastIndexOf("/") + 1))
                .collect(Collectors.toList());
        String fileNames = JSONUtil.toJsonStr(fileNameList);

        ResultSave resultSave = ResultSave.builder()
                .params(ObjUtil.toStr(vo))
                .resultData(JSONUtil.toJsonStr(resultDataList))
                .fileNames(fileNames)
                .startTime(vo.getStartTime())
                .endTime(vo.getEndTime())
                .module(ResultSaveModule.MODEL_REVISE)
                .submodule(ResultSaveModule.MODEL_REVISE_CHARACTER)
                .createTime(new Date())
                .build();

        resultSaveService.save(resultSave);

        Map<String,Object> resultMap = new LinkedHashMap<>();

        resultMap.put("resultData", JSONUtil.toJsonStr(resultDataList));
        resultMap.put("module", ResultSaveModule.MODEL_REVISE);
        resultMap.put("submodule", ResultSaveModule.MODEL_REVISE_CHARACTER);

        return AjaxResult.success(resultMap);

    }


    @PostMapping("/draw")
    @ApiOperation(value = "风场特征-绘制", notes = "根据页面入参计算出结果文件", httpMethod = "POST")
    public AjaxResult windCharacterDraw(@RequestBody WindCharacterDrawVo vo) {

        String tmpDir = PathUtil.tmpDir() +
                PathUtil.moduleDirs().getModelRevise().get("dir");

        String outputDir = PathUtil.outputDir() +
                PathUtil.moduleDirs().getModelRevise().get("dir");

        String type = vo.getType();

        String command="";
        if ("satellite".equals(type)){
            String codePath = PathUtil.codeDir() +
                    PathUtil.moduleDirs().getModelRevise().get("dir") +
                    PathUtil.moduleDirs().getModelRevise().get("satellite_plot");

            String area = CommonUtil.getArea(vo.getLongitudeRange(), vo.getLatitudeRange());
            String resultType = vo.getResultType();
            String level = ("horizon".equals(resultType) || "trajectory".equals(resultType))?vo.getLevel():"all";
            String dataType = StrUtil.isBlank(vo.getDataType())? "None":vo.getDataType();
            command = "python "+codePath+" "+outputDir+" "+tmpDir+" "+vo.getSateName()+" "+ dataType + " "
                    +vo.getStartTime() +" "+vo.getEndTime() +" "+vo.getFactor()+" "+vo.getResultType()+" "+area+" "+level+" "+vo.getMethod();
        }

        if ("radar".equals(type)){

            String codePath = PathUtil.codeDir() +
                    PathUtil.moduleDirs().getModelRevise().get("dir") +
                    PathUtil.moduleDirs().getModelRevise().get("radar_plot");

            command = "python "+codePath+" "+outputDir+" "+tmpDir+" "+vo.getDataName()+" "
                    +vo.getStartTime() +" "+vo.getEndTime() +" "+vo.getFactor()+" "+vo.getTimeFeature();
        }
        String results = ExecUtil.execCmdWithResult(command);
        if (results == null || !results.contains("###")){
            return AjaxResult.error(results);
        }

        //2024-10-14 轨迹是数据
        if (StrUtil.isNotBlank(vo.getResultType()) && "trajectory".equals(vo.getResultType())){
            String[] splitArr = results.split("###");
            Map<String,Object> resultMap = new LinkedHashMap<>();
            resultMap.put("log", splitArr[0]);
            resultMap.put("data", splitArr[1]);
            return AjaxResult.success(resultMap);
        }

        HashMap<String, String> pathMap = new HashMap<>();
        String[] splitArr = results.split("###");
        int index = 1;
        for (int i = 0; i < splitArr.length; i++) {
            String path =splitArr[i];
            if (path.contains(".png") || path.contains(".PNG")){
                pathMap.put("path"+index, path.trim());
                index++;
            }
        }

        return AjaxResult.success("",JSONUtil.toJsonStr(pathMap));
    }

    @ApiOperation(value = "建立连接", notes = "建立连接")
    @GetMapping(path = "subscribe", produces = {MediaType.TEXT_EVENT_STREAM_VALUE})
    public SseEmitter push(String id, String flag) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        return SseEmitterUtils.connect(id+loginUser.getUsername(), flag);
    }


}
